Add support for alternate lookups to Cache<T>#9721
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds zero-allocation span-based lookup overloads to Cache<TValue> for .NET 9+, leveraging ConcurrentDictionary.AlternateLookup<ReadOnlySpan<char>> so callers can probe and read the cache without first materializing a string. String allocation only happens on the miss path when a new entry must be inserted.
Changes:
- Introduce a
_spanLookupfield initialized from_map.GetAlternateLookup<ReadOnlySpan<char>>(), guarded by#if NET9_0_OR_GREATER. - Add
TryGet,TryAdd, and twoGetOrCreateoverloads acceptingReadOnlySpan<char>keys; misses fall back to string allocation and the existing string-keyed paths. - Add unit tests covering hit/miss/non-overwrite/factory-invocation/state-passing semantics, plus a cross-lookup test ensuring string and span lookups operate on the same underlying map.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/HotChocolate/Caching/src/Caching.Memory/Cache.cs | Adds span-keyed TryGet/TryAdd/GetOrCreate overloads and an alternate-lookup field for .NET 9+. |
| src/HotChocolate/Caching/test/Caching.Memory.Tests/CacheTests.cs | Adds tests for the new span-based APIs, including cross-keying with the existing string APIs. |
Comments suppressed due to low confidence (1)
src/HotChocolate/Caching/src/Caching.Memory/Cache.cs:322
- On a miss,
GetOrCreate(ReadOnlySpan<char>, ..., TState)materializes the key viakey.ToString()and forwards to the string-keyedGetOrCreate, which then performs another_map.TryGetValuebefore falling through toGetOrAdd. This makes the miss path do two dictionary lookups (one via the alternate span lookup at line 309, and another via the string-keyed map in the forwarded call). Consider calling_map.GetOrAdd(key.ToString(), ...)directly here, mirroring the string-keyed implementation, to avoid the redundant lookup on the slow path.
// On a miss, we materialize the key and delegate to the string-keyed overload
// so the single-race-winner invariant of GetOrAdd is preserved.
return GetOrCreate(key.ToString(), create, state);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This was referenced May 20, 2026
This was referenced May 27, 2026
This was referenced Jun 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.